package com.example.scg.route;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.data.domain.PageRequest;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

/**
 * @author Aaron
 */
@Slf4j
@Component
@ConditionalOnProperty(value = "route.schedule.enabled", havingValue = "true", matchIfMissing = true)
public class RouteRefresher {

  private final MongoRouteDefinitionRepository repository;

  public RouteRefresher(
      MongoRouteDefinitionRepository repository) {
    this.repository = repository;
  }

  /**
   * 固定间隔重新加载一次缓存
   */
  @Scheduled(initialDelay = 10000, fixedDelay = 60 * 60 * 1001)
  private void refresh() {
    RouteRepositoryOperations operation = repository.getRepositoryOperation();

    int page = 0;
    int pageSize = 1000;
    int total = Math.toIntExact(operation.count().blockOptional().orElse(0L));
    Map<String, RouteDefinition> oldCache = repository.getCache();
    Map<String, RouteDefinition> newCache = new ConcurrentHashMap<>(total);
    int oldTotal = oldCache.size();
    if (oldTotal < 1) {
      // 首次同步刷新
      repository.setCache(newCache);
    }
    while (page * pageSize < total) {
      operation.findAll(PageRequest.of(page++, pageSize))
          .doOnNext(route -> newCache.putIfAbsent(route.getId(), route))
          .blockLast();
      log.info("动态路由表当前总大小为：{}, 新路由表当前大小为：{}", oldTotal, newCache.size());
    }
    repository.setCache(newCache);
    log.info("新路由表加载完成，当前大小为：{}", newCache.size());
    oldCache.clear();
    repository.publishEvent();
  }
}
